package com.asiainfo.codeclean;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

/**
 * <pre>
 *   适用于该类错误 Use a logger to log this exception. private static final
 *   org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger();
 * </pre>
 */
public class CodeCleanSlf4j {

	Set<Path> ps;

	{
		scan(/**/

				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-web/src/main/java"
//				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-fileserver/src/main/java", 
//				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-timer/src/main/java", 
//				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-support/src/main/java", 
//				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-quickstart/src/main/java",
//				"E:/java/j2ee/GZ-projects/yth/zsale/zsale-framework/src/main/java"

		/**/);
	}

	@Test
	public void doClean() throws Exception {
		int count = 1;
		for (Path path : ps) {
			String oldCode = new String(Files.readAllBytes(path));
			File file = path.toFile();
			String filePath = file.toString();
			String className = file.getName().replaceAll("(\\S+)\\.java", "$1");
			List<Segment> segments = Segment.splitSegment(oldCode);
			String simpleCode = Segment.toSimpleCode(segments);
			if (simpleCode.matches("([\\s\\S]*)([\\r\\n]\\s*)(\\w*)\\.printStackTrace\\(\\s*\\);\\s*([\\r\\n])([\\s\\S]*)")) {
				String loggerFieldName = findLoggerFieldName(segments, className);
				if (loggerFieldName == null) {
					String logStmt = "private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(" + className + ".class);";
					String code = Segment.toCode(segments);
					code = code.replaceAll("^([\\s\\S]*?class\\s*?" + className + "[\\s\\S]+?)(\\{)([\\s\\S]+\\}\\s*)$", "$1$2\r\n\r\n\t" + logStmt + "\r\n$3");
					segments = Segment.splitSegment(code);
					loggerFieldName = "logger";
				}
				replacePrintStackTraceAndTODO(segments, loggerFieldName);
				file.renameTo(new File(filePath + ".bak"));
				saveFile(filePath, Segment.toCode(segments));
				System.out.println(String.format("%d. %s ==> %s", count++, className, filePath));
			}
		}
		System.out.println("\n整理完成。。。");
	}

	private String findLoggerFieldName(List<Segment> segments, String className) {
		for (Segment segment : segments) {
			if (segment.isComment())
				continue;
			Matcher m = Pattern.compile("\\s(\\w+)\\s*?=\\s*?.*?LoggerFactory\\.getLogger\\(.*?\\).*?;.*?").matcher(segment.getContent());
			if (m.find()) {
				return m.group(1);
			}
		}
		return null;
	}

	private void replacePrintStackTraceAndTODO(List<Segment> segments, String loggerFieldName) {
		for (Segment segment : segments) {
			if (segment.isComment()) {
				// 清除TODO
				segment.setContent(segment.getContent().replaceAll("([\\r\\n]?)(.*// TODO.*)([\\r|\\n]?)", ""));
			} else {
				// 替换 e.printStackTrace();
				segment.setContent(segment.getContent().replaceAll("([\\r\\n]\\s*)(\\w*)\\.printStackTrace\\(\\s*\\);\\s*([\\r\\n])", "$1" + loggerFieldName + ".error(\"\",$2);$3"));

			}
		}
	}

	// @Test
	public void doRecovery() throws IOException {
		int count = 1;
		for (Path path : ps) {
			File file = path.toFile();
			String filePath = file.toString();
			File bak = new File(filePath + ".bak");
			if (bak.exists()) {
				file.delete();
				bak.renameTo(new File(filePath));
				System.out.println(String.format("%d. %s", count++, filePath));
			}
		}
		System.out.println("\n恢复完成。。。");
	}

	@Test
	public void doDeleteBakupFile() throws IOException {
		int count = 1;
		for (Path path : ps) {
			File file = path.toFile();
			String filePath = file.toString();
			File bak = new File(filePath + ".bak");
			if (bak.exists()) {
				bak.delete();
				System.out.println(String.format("%d. %s", count++, filePath));
			}
		}
		System.out.println("\n删除完成。。。");
	}

	private void saveFile(String oldPath, String code) throws IOException {
		Files.write(Paths.get(oldPath), code.getBytes());
	}

	public void scan(String... dirs) {
		try {
			this.ps = new HashSet<Path>();
			for (String dir : dirs) {
				Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor<Path>() {
					@Override
					public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
						if (file.getFileName().toString().endsWith(".java")) {
							ps.add(file);
						}
						return FileVisitResult.CONTINUE;
					}
				});
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

}
